/* 
 * File:   operacoes.cpp
 * Author: Saulo
 * 
 * Created on 23 de Maio de 2010, 22:24
 */

#include "operacoes.h"
#include <iostream>

using namespace std;

operacoes::operacoes() {
}

operacoes::operacoes(const operacoes& orig) {
}

operacoes::~operacoes() {
}

//Instrução

reg operacoes::i_add(reg a, reg b) {
    reg c;
    c = this->soma16bits(a, b);
    return c;
}

//Instrução 2

reg operacoes::i_addinc(reg a, reg b) {
    reg c;
    c.valor = a.valor + a.valor + 1;
    return c;
}

//Instrução 3

reg operacoes::i_and(reg b, reg a) {
    reg c;
    c.valor = b.valor & a.valor;
    return c;
}

//Instrução 4

reg operacoes::i_andnota(reg a, reg b) {
    reg c;
    c.valor = (!a.valor) & b.valor;
    return c;
}

//Instrução 7

reg operacoes::i_deca(reg a) {
    reg c;
    c.valor = a.valor - 1;
    return c;
}

//Instrução 8

reg operacoes::i_inca(reg a) {
    reg c;
    c.valor = a.valor + 1;
    return c;
}

//Instrução 18

reg operacoes::i_lsl(reg a) {
    reg c;
    c.valor = a.valor << 1;
    return c;
}

//Instrução 19

reg operacoes::i_lsr(reg a) {
    reg c;
    c.valor = a.valor >> 1;
    return c;
}
//Instrução 20

reg operacoes::i_nand(reg a, reg b) {
    reg c;
    c.valor = (!a.valor) & b.valor;
    return c;
}

//Instrução 21

reg operacoes::i_nor(reg a, reg b) {
    reg c;
    c.valor = !(a.valor | b.valor);
    return c;
}

//Instrução 22

reg operacoes::i_ones() {
    reg c;
    c.valor = 1;
    return c;
}

//Instrução 23

reg operacoes::i_or(reg a, reg b) {
    reg c;
    c.valor = a.valor | b.valor;
    return c;
}

//Instrução 24

reg operacoes::i_ornotb(reg a, reg b) {
    reg c;
    c.valor = a.valor | (!b.valor);
    return c;
}

//Instrução 25

reg operacoes::i_passa(reg a) {
    reg c;
    c.valor = a.valor;
    return c;
}

//Instrução 26

reg operacoes::i_passnota(reg a) {
    reg c;
    c.valor = !a.valor;
    return c;
}

//Instrução 28

reg operacoes::i_sub(reg a, reg b) {
    reg c;
    c.valor = a.valor - b.valor;
    return c;
}

//Instrução 29

reg operacoes::i_subdec(reg a, reg b) {
    reg c;
    c.valor = a.valor - b.valor - 1;
    return c;
}

//Instrução 30

reg operacoes::i_xnor(reg a, reg b) {
    reg c;
    c.valor = !(a.valor^b.valor);
    return c;
}

//Instrução 31

reg operacoes::i_xor(reg a, reg b) {
    reg c;
    c.valor = a.valor^b.valor;
    return c;
}

//Instrução 32

reg operacoes::i_zeros() {
    reg c;
    c.valor = 0;
    return c;
}

reg operacoes::i_addi(reg a, int b) {
    reg c;
    c.valor = a.valor + b;
    return c;
}


//========================================================

unsigned operacoes::soma(unsigned* carryOut, unsigned carryIn, unsigned a, unsigned b) {
    unsigned resultado;
    if (carryIn == 0 && a == 0 && b == 0){*carryOut = 0; resultado = 0;}
    if (carryIn == 0 && a == 0 && b == 1){*carryOut = 0; resultado = 1;}
    if (carryIn == 0 && a == 1 && b == 0){*carryOut = 0; resultado = 1;}
    if (carryIn == 0 && a == 1 && b == 1){*carryOut = 1; resultado = 0;}
    if (carryIn == 1 && a == 0 && b == 0){*carryOut = 0; resultado = 1;}
    if (carryIn == 1 && a == 0 && b == 1){*carryOut = 1; resultado = 0;}
    if (carryIn == 1 && a == 1 && b == 0){*carryOut = 1; resultado = 0;}
    if (carryIn == 1 && a == 1 && b == 1){*carryOut = 1; resultado = 1;}

    return   resultado;

}

reg operacoes::soma16bits(reg A, reg B) {
    reg Result;
    Result.valor = 0;
    unsigned carry;
    carry = 0;
    Result.campos.b0 = this->soma(&carry, carry, A.campos.b0, B.campos.b0);
    Result.campos.b1 = this->soma(&carry, carry, A.campos.b1, B.campos.b1);
    Result.campos.b2 = this->soma(&carry, carry, A.campos.b2, B.campos.b2);
    Result.campos.b3 = this->soma(&carry, carry, A.campos.b3, B.campos.b3);
    Result.campos.b4 = this->soma(&carry, carry, A.campos.b4, B.campos.b4);
    Result.campos.b5 = this->soma(&carry, carry, A.campos.b5, B.campos.b5);
    Result.campos.b6 = this->soma(&carry, carry, A.campos.b6, B.campos.b6);
    Result.campos.b7 = this->soma(&carry, carry, A.campos.b7, B.campos.b7);
    Result.campos.b8 = this->soma(&carry, carry, A.campos.b8, B.campos.b8);
    Result.campos.b9 = this->soma(&carry, carry, A.campos.b9, B.campos.b9);
    Result.campos.b10 = this->soma(&carry, carry, A.campos.b10, B.campos.b10);
    Result.campos.b11 = this->soma(&carry, carry, A.campos.b11, B.campos.b11);
    Result.campos.b12 = this->soma(&carry, carry, A.campos.b12, B.campos.b12);
    Result.campos.b13 = this->soma(&carry, carry, A.campos.b13, B.campos.b13);
    Result.campos.b14 = this->soma(&carry, carry, A.campos.b14, B.campos.b14);
    Result.campos.b15 = this->soma(&carry, carry, A.campos.b15, B.campos.b15);
    return Result;
}